﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using DeepEarth.Core;
using System.Collections.ObjectModel;
using System.Collections;
using DeepEarth.Map.Core;
using DeepEarth.Toolkit.Geometry.Data;

namespace ExampleApplication.Examples
{
    public partial class DataBinding : Page
    {
        public DataBinding()
        {
            InitializeComponent();
        }

        // Executes when the user navigates to this page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            Bind();
        }

        void Bind()
        {
            // A collection of items that should be treated as a single feature
            // The items in this collection won't appear in the layer panel
            MyGroup atomicItemsCollection = new MyGroup("Atomic - Drag to Change Z", true);

            MyPointItem aPoint = new MyPointItem { Latitude = -15, Longitude = 25 };
            aPoint.Color = new SolidColorBrush(Colors.Yellow);
            aPoint.Name = "This is a Pushpin";
            atomicItemsCollection.Add(aPoint);

            MyPolyItem aPoly = new MyPolyItem();
            aPoly.Name = "This is a Polygon";
            aPoly.StrokeThickness = 5;
            aPoly.Stroke = new SolidColorBrush(Colors.Black);
            aPoly.Fill = new SolidColorBrush(Colors.Orange);
            aPoly.Locations.Add(new Location(20, -20));
            aPoly.Locations.Add(new Location(-10, -20));
            aPoly.Locations.Add(new Location(-10, 10));
            aPoly.Locations.Add(new Location(20, 10));
            aPoly.Locations.Add(new Location(20, -20));
            atomicItemsCollection.Add(aPoly);

            // A non atomic collection. The items in this collection will appear in the layer panel
            MyGroup ordinaryItemsCollection = new MyGroup("Ordinary - Drag to Change Z", false);
            MyPointItem oPoint = new MyPointItem { Latitude = 10, Longitude = -10 };
            oPoint.Color= new SolidColorBrush(Colors.Green);
            oPoint.Name = "This is a Pushpin too";
            ordinaryItemsCollection.Add(oPoint);

            MyPolyItem oPoly = new MyPolyItem();
            oPoly.Name = "This is a Polygon too";
            oPoly.StrokeThickness = 5;
            oPoly.Stroke = new SolidColorBrush(Colors.White);
            oPoly.Fill = new SolidColorBrush(Colors.Blue);
            oPoly.Locations.Add(new Location(10, -10));
            oPoly.Locations.Add(new Location(-30, -10));
            oPoly.Locations.Add(new Location(-30, 30));
            oPoly.Locations.Add(new Location(10, 30));
            oPoly.Locations.Add(new Location(10, -10));
            ordinaryItemsCollection.Add(oPoly);

            MyLineItem oLine = new MyLineItem();
            oLine.Name = "A Line";
            oLine.StrokeThickness = 8;
            oLine.Stroke = new SolidColorBrush(Colors.White);
            oLine.Locations.Add(new Location(-40, -40));
            oLine.Locations.Add(new Location(40, 40));
            ordinaryItemsCollection.Add(oLine);

            // Create a collection of groups, add them to a single collection for the GeoItemsControl.
            List<MyGroup> groups = new List<MyGroup>();
            groups.Add(atomicItemsCollection);
            groups.Add(ordinaryItemsCollection);
            this.geoItems.ItemsSource = groups;
        }
    }

    public abstract class MyBaseItem
    {
        public string Name { get; set; }
    }

    public class MyPointItem : MyBaseItem, ISelectable
    {
        public SolidColorBrush Color { get; set; }

        public double Latitude { get; set; }
        public double Longitude { get; set; }

        private Location position;
        public Location Position
        {
            get
            {
                if (position == null)
                {
                    position = new Location { Latitude = Latitude, Longitude = Longitude };
                }
                return position;
            }
            set
            {
                this.position = value;
            }
        }

        private PositionOrigin positionOrigin = new PositionOrigin(0.5, 1.0);
        public PositionOrigin PositionOrigin
        {
            get
            {
                return positionOrigin;
            }
            set
            {
                this.positionOrigin = value;
            }
        }

        #region ISelectable
        public ICommand SelectionCommand { get; set; }
        #endregion
    }

    public class MyHierarchicalItem : MyPointItem
    {
        public ObservableCollection<MyBaseItem> NestedItems { get; set; }

        public MyHierarchicalItem(double latitude, double longitude)
        {
            this.Latitude = latitude;
            this.Longitude = longitude;
            NestedItems = new ObservableCollection<MyBaseItem>();
        }

        public void Add(MyBaseItem childItem)
        {
            this.NestedItems.Add(childItem);
        }
    }

    public abstract class MyVectorItem : MyBaseItem
    {        
        public ObservableCollection<Location> Locations { get; set; }

        public SolidColorBrush Stroke { get; set; }
        public double StrokeThickness { get; set; }

        public MyVectorItem()
        {
            Locations = new ObservableCollection<Location>();
        }
    }

    public class MyLineItem : MyVectorItem
    {
    }

    public class MyPolyItem : MyVectorItem
    {
        public SolidColorBrush Fill { get; set; }
    }

    // MyGroup implements IItemsContainer - When databound via a GeoItems control, an ItemsContainer will be
    // rendered in it's own "Layer".
    public class MyGroup : IItemsContainer
    {
        public MyGroup(string name, bool isAtomic)
        {
            Name = name;
            IsAtomic = isAtomic;
            Items = new List<MyBaseItem>();
        }

        public string Name { get; set; }

        List<MyBaseItem> Items { get; set; }

        public IEnumerable Children
        {
            get { return Items; }
        }

        public double Opacity
        {
            get { return 1.0; }
        }

        public bool IsAtomic { get; set; }

        public ActivationCascadeMode ActivationCascade
        {
            get
            {
                return  ActivationCascadeMode.Activate | ActivationCascadeMode.Deactivate;
            }
        }

        public void Add(MyBaseItem item)
        {
            Items.Add(item);
        }
    }
}
